const mongoose = require("mongoose");
const config = require("../bin/dbConfig");

class DB {
  constructor() {
    // connect() 返回一个状态待定（pending）的连接
    this.connection = null;
    console.log("ok! 现在已经可以尝试连接！");
    // 具体在构造函数中是否调用connect() 调用可以检测连接DB的情况 可以不调用,在postman调试即可
    // this.connect()
  }
  connect() {
    return new Promise((resolve, reject) => {
      try {
        //第一次创建连接的时候this.connection还没保存任何东西
        // this.connection要来保存一个状态待定（pending）的连接
        if (!this.connection) {
          // connect() 返回一个状态待定（pending）的连接
          console.log("this.connection is", this.connection);
          this.connection = mongoose.connect(config.dbUrl + config.dbName);

          // 这里resolve可以不给参数  因为连接的this.connection已经在构造器里声明过了
          // resolve(this.connection);
          resolve();
        } else {
          // resolve(this.connection);
          resolve();
        }
      } catch (error) {
        reject("数据库连接失败");
      }

      // 监听MongoDB数据库链接状态
      // 数据库链接成功事件之后回调
      mongoose.connection.once("open", function () {
        console.log("数据库连接成功~~~");
      });

      // 数据库断开事件之后回调
      mongoose.connection.once("close", function () {
        console.log("数据库断开连接~~~");
      });
    });
  }
  /* 
  tableName:集合名
  conditions:查询条件
  projecttion:投影
  options:查询选项{skip:Number,limit:Number}
  schema:约束文档
  */

  // Mongodb中的document相当于是mysql的一条行数据
  find({ tableName, conditions, projecttion = null, options = null, schema }) {
    return new Promise((resolve, reject) => {
      try {
        // connect() 函数接受回调函数，或返回一个 promise。
        this.connect().then(() => {
          let models = mongoose.model(tableName, schema);
          // models可以直接调用CRUD的操作
          // 查询文档可以用 model 的 find, findById, findOne, 和 where 这些静态方法
          models
            .find(conditions, projecttion, options, (err, docs) => {
              if (!err) {
                resolve(docs);
              } else {
                reject(err);
              }
            })
            .lean();
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  findByconditions({
    tableName,
    conditions,
    projecttion = null,
    skip = 0,
    limit = 0,
    schema,
  }) {
    return new Promise((resolve, reject) => {
      try {
        this.connect().then(() => {
          let models = mongoose.model(tableName, schema);
          models
            .find(conditions, projecttion, (err, docs) => {
              if (!err) {
                resolve(docs);
              } else {
                reject(err);
              }
            })
            .skip(skip)
            .limit(limit);
        });
      } catch (error) {
        reject(error);
      }
    });
  }
  /* 
  tableName:集合名
  conditions:查询条件
  doc:修改后的对象
  options:查询选项{skip:Number,limit:Number}
  schema:约束文档
  */
  update({ tableName, conditions, doc, options = null, schema }) {
    return new Promise((resolve, reject) => {
      try {
        this.connect().then(() => {
          let models = mongoose.model(tableName, schema);
          models.updateMany(conditions, doc, options, (err) => {
            if (!err) {
              resolve("1");
            } else {
              reject(err);
            }
          });
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /* 
  tableName:集合名
  doc:新增的对象
  schema:约束文档
  */
  insert({ tableName, doc, schema }) {
    return new Promise((resolve, reject) => {
      try {
        this.connect().then(() => {
          let models = mongoose.model(tableName, schema);
          models.create(doc, (err, jellybean, snickers) => {
            console.log(jellybean); //添加成功的文档
            console.log(snickers);
            if (!err) {
              resolve(jellybean);
            } else {
            }
          });
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /* 
  tableName:集合名
  conditions:查询条件
  schema:约束文档
  */
  delete({ tableName, conditions, schema }) {
    return new Promise((resolve, reject) => {
      try {
        this.connect().then(() => {
          let models = mongoose.model(tableName, schema);
          models.remove(conditions, (err) => {
            if (!err) {
              resolve("success");
            } else {
              reject(err);
            }
          });
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /* 
  tableName:集合名
  conditions:查询条件
  schema:约束文档
  */
  count({ tableName, conditions, schema }) {
    return new Promise((resolve, reject) => {
      try {
        this.connect()
          .then(() => {
            let models = mongoose.model(tableName, schema);
            models.count(conditions, (err, counts) => {
              if (!err) {
                resolve(counts);
              } else {
                reject(err);
              }
            });
          })
          .catch((err) => {
            reject(err);
          });
      } catch (error) {
        reject(error);
      }
    });
  }
}
module.exports = new DB();
